<template>
	<div
		:class="[
			'app-editor-container',
			'app-mob-custom-dropdown-list',
			`app-mob-custom-dropdown-list-${name}`,
		]"
	>
		<van-field
			readonly
			type="text"
			v-model="textValue"
			:disabled="disabled"
			@click="setPopupState(true)"
		>
			<template #right-icon>
				<van-icon v-if="textValue" name="clear" @click="handleClear" />
				<van-icon name="arrow-down" />
			</template>
		</van-field>
		<van-popup
			round
			teleport="body"
			position="bottom"
			v-model:show="popupState"
			class="custom-dropdown-list__popup"
		>
			<div class="popup__container">
				<div class="popup__header">
					<div @click="cancel" class="cancel">
						{{ $t('common.generic.onCancel', '取消') }}
					</div>
					<div @click="confirm" class="confirm">
						{{ $t('common.generic.okText', '确定') }}
					</div>
				</div>
                <div class="popup__content">
                    <AppMobTree
                        v-bind="$attrs"
                        :fieldNames="fieldNames"
                        :multiple="multiple"
                        :items="items"
                        :selectedKeys="selectedKeys"
                        @selectionChange="handleSelectChange"
                    />
                </div>
			</div>
		</van-popup>
	</div>
</template>
<script lang="ts" setup>
import { computedNavData, deepCopy, IEvent, IParam, typeOf } from '@/core';
import { Http } from '@/http';
import { Ref } from 'vue';
import { customDropdownListProps } from './custom-dropdown-list';
import { useEditorTypeParams } from '@/hooks/use-editor';
interface EditorEmit {
	(name: 'editor-event', value: IEvent<string>): void;
}
const props = defineProps(customDropdownListProps);
const emit = defineEmits<EditorEmit>();
// 类型校验
const {
	validateConfig,
	valueType,
	valueSeparator,
	objectNameField,
	objectIdField,
	objectValueField,
} = useEditorTypeParams();
validateConfig();
/**
 * 模态状态
 */
const popupState = ref(false);
/**
 * 树形数据
 */
const items: Ref<IParam[]> = ref([]);
/**
 * 选中值key集合
 */
const selectedKeys: Ref<string[]> = ref([]);
/**
 * 树节点配置
 */
const fieldNames = computed(() => {
	const tempData: any = {
		text: 'label',
		value: 'value',
		options: 'children',
		leaf: 'isLeaf',
	};
	Object.assign(tempData, props.fieldMap);
	if (props.fieldMap && props.fieldMap['label']) {
		Object.assign(tempData, {
			text: props.fieldMap['label'],
		});
	}
	return tempData;
});
/**
 * 当前url
 */
let curUrl: string = '';
/**
 * 数据集合
 */
let data: IParam[] = [];
/**
 * @description 初始化选中数据
 */
const initSelectData = () => {
	const valueName: string = fieldNames.value['value'];
	if (props.multiple) {
		if (Object.is(valueType, 'SIMPLES')) {
			selectedKeys.value = (props.value as string[]) || [];
		} else if (Object.is(valueType, 'OBJECTS')) {
			let values: any[] = [];
			(props.value as any[]).forEach((_item: any) => {
				values.push(_item[valueName]);
			});
			selectedKeys.value = values;
		} else {
			selectedKeys.value =
				(props.value as string)?.split(
					valueSeparator ? valueSeparator : props.valueSeparator
				) || [];
		}
	} else {
		if (Object.is(valueType, 'OBJECTS')) {
			selectedKeys.value = (props.value as string)
				? [(props.value as any)[valueName]]
				: [];
		} else {
			selectedKeys.value = (props.value as string)
				? [props.value as string]
				: [];
		}
	}
};
watch(
	() => props.data,
	(newVal: IParam, oldVal: IParam) => {
		load();
		if (newVal[props.name] !== oldVal[props.name]) {
			initSelectData();
		}
	}
);
/**
 * @description 设置模态状态
 * @param state  状态
 */
const setPopupState = (state: boolean) => {
	if (props.disabled) {
		return;
	}
	popupState.value = state;
};
/**
 * 显示文本
 */
const textValue = computed(() => {
	let value: any;
	try {
		let _data: any = deepCopy(props.value as any);
		if (_data) {
			const valueName: string = fieldNames.value['value'];
			const textName: string = fieldNames.value['label'];
			let values: any[] = [];
			let text: string[] = [];
			if (props.multiple) {
				if (valueType == 'SIMPLES') {
					values = _data;
				} else if (valueType == 'OBJECTS') {
					_data.forEach((_item: any) => {
						values.push(_item[valueName]);
					});
				} else {
					values =
						_data.split(
							valueSeparator ? valueSeparator : props.valueSeparator
						) || [];
				}
			} else {
				values = [_data];
			}
			if (values && values.length > 0) {
				values.forEach((value: string) => {
					const item = data.find((item: IParam) =>
						Object.is(item[valueName], value)
					);
					if (item) {
						text.push(item[textName]);
					}
				});
			}
			value = text.join(valueSeparator ? valueSeparator : props.valueSeparator);
		}
	} catch (error) {
		console.log(error);
	}
	return value;
});
/**
 * @description 加载数据
 */
const load = () => {
	const tempUrl = computeUrl();
	if (tempUrl && tempUrl != curUrl) {
		curUrl = tempUrl;
		data = [];
		const _data = computedNavData(
			props.data,
			props.context,
			props.viewParams,
			props.filterParams
		);
		Http.getHttp()
			[props.method](tempUrl, _data)
			.then((response: any) => {
				if (!response || !response.success) {
					App.getNotificationHelper().error(
						App.ts('common.customdropdownlist.loadfail', '数据加载失败')
					);
					return;
				}
				if (response.data && response.data.length > 0) {
					data = [...response.data];
					handleItems(response.data);
				}
			})
			.catch((error: any) => {
				App.getNotificationHelper().error(
					App.ts('common.customdropdownlist.loadfail', '数据加载失败')
				);
			});
	} else {
		App.getNotificationHelper().error(
			App.ts('common.customdropdownlist.nourl', '无数据加载路径')
		);
	}
};
/**
 * @description 计算数据请求路径
 */
const computeUrl = () => {
	let url = props.url;
	const tempMap = props.urlMap ? Object.keys(props.urlMap) : [];
	if (url && tempMap && tempMap.length > 0) {
		tempMap.forEach((item: string) => {
			const tempValue = props.urlMap[item];
			let targetValue = null;
			if (props.data.hasOwnProperty(tempValue)) {
				targetValue = props.data[tempValue];
			} else if (props.context.hasOwnProperty(tempValue)) {
				targetValue = props.context[tempValue];
			} else if (props.viewParams.hasOwnProperty(tempValue)) {
				targetValue = props.viewParams[tempValue];
			}
			const str = '${' + item + '}';
			url = url.replaceAll(str, targetValue);
		});
	}
	return url;
};
/**
 * @description 处理数据集
 * @param data  数据集合
 */
const handleItems = (data: IParam[]) => {
	if (fieldNames.value) {
		const parentId = fieldNames.value['pid'];
		if (parentId) {
			items.value = handleChildren(data, parentId, fieldNames.value['value']);
			return;
		}
	}
	items.value = data;
};
/**
 * @description 处理父子数据
 * @param data  数据集合
 * @param parentId  父节点id
 * @param curValue  当前值名称
 */
const handleChildren = (data: IParam[], parentId: string, curValue: string) => {
	let tempData: any[] = [];
	const setChildItems = (
		pValue: string,
		result: Array<IParam>,
		curItem: IParam
	) => {
		result.forEach((item: IParam) => {
			if (item[parentId] == pValue) {
				let valueField: string = item[curValue];
				setChildItems(valueField, result, item);
				if (!curItem[fieldNames.value['options']]) {
					curItem[fieldNames.value['options']] = [];
				}
				curItem[fieldNames.value['options']].push(item);
			}
		});
		if (
			!curItem[fieldNames.value['options']] ||
			curItem[fieldNames.value['options']].length == 0
		) {
			curItem[fieldNames.value['options']] = [];
			curItem[fieldNames.value['leaf']] = true;
		}
	};
	data.forEach((curItem: IParam) => {
		if (!curItem[parentId]) {
			let valueField: string = curItem[curValue];
			setChildItems(valueField, data, curItem);
			tempData.push(curItem);
		}
	});
	return tempData;
};
/**
 * @description 取消
 */
const cancel = () => {
	initSelectData();
	setPopupState(false);
};
/**
 * @description 确定
 */
const confirm = () => {
	let value: any = handleSelectData();
	doEditorEmit(value);
	setPopupState(false);
};
/**
 * @description 处理值改变
 * @param selected  选中数据集合
 */
const handleSelectChange = (selected: IParam[]) => {
	const value: string[] = [];
	selected.forEach((select: IParam) => {
		value.push(select[fieldNames.value['value']]);
	});
	selectedKeys.value = value;
};
/**
 * @description 处理选中数据
 */
const handleSelectData = (): any => {
	let result: any = null;
	const valueName: string = fieldNames.value['value'];
	const handleObjectParams = (item: IParam, selectId: string): IParam => {
		const object: IParam = { [valueName]: selectId };
		if (objectNameField) {
			Object.assign(object, {
				[objectNameField]: item[objectNameField],
			});
		}
		if (objectIdField) {
			Object.assign(object, {
				[objectIdField]: item[objectIdField],
			});
		}
		if (objectValueField) {
			Object.assign(object, {
				[objectValueField]: deepCopy(item),
			});
		}
		return object;
	};
	if (props.multiple) {
		const curSelectValue: any[] = [];
		selectedKeys.value.forEach((select: string) => {
			if (valueType == 'OBJECTS') {
				const item = data.find((item: IParam) =>
					Object.is(select, item[valueName])
				);
				if (item) {
					curSelectValue.push(handleObjectParams(item, select));
				}
			} else {
				curSelectValue.push(select);
			}
		});
		if (curSelectValue.length > 0) {
			result =
				Object.is(valueType, 'SIMPLES') || Object.is(valueType, 'OBJECTS')
					? curSelectValue
					: curSelectValue.join(
							valueSeparator ? valueSeparator : props.valueSeparator
					  );
		}
	} else {
		let select: string | null = selectedKeys.value[0]
			? selectedKeys.value[0]
			: null;
		if (select) {
			if (valueType == 'OBJECT') {
				const item = data.find((item: IParam) =>
					Object.is(select, item[valueName])
				);
				if (item) {
					result = handleObjectParams(item, select);
				}
			} else {
				result = select;
			}
		}
	}
	return result;
};
/**
 * @description 清除
 * @param event 事件源
 */
const handleClear = (event: MouseEvent) => {
	event.preventDefault();
	event.stopPropagation();
	doEditorEmit(null);
};
/**
 * @description 编辑器事件抛出
 */
const doEditorEmit = (value: any) => {
	emit('editor-event', {
		name: `${props.name}`,
		action: 'valueChange',
		data: value,
	});
};
</script>